package com.qikux.service.impl;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.mail.MailUtil;
import com.qikux.annotation.Component;
import com.qikux.annotation.Resource;
import com.qikux.annotation.Transactional;
import com.qikux.consts.AppConst;
import com.qikux.consts.UserStatus;
import com.qikux.dao.DetailDao;
import com.qikux.dao.UserDao;
import com.qikux.dao.impl.DetailDaoImpl;
import com.qikux.entity.Notice;
import com.qikux.entity.User;
import com.qikux.entity.UserInfo;
import com.qikux.entity.UserScore;
import com.qikux.service.UserService;
import com.qikux.utils.ContextUtils;
import com.qikux.utils.RSAUtils;
import com.qikux.utils.SendMailUtils;
import com.qikux.vo.Page;
import com.qikux.vo.ResultVo;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;

@Component
@Transactional
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userDao;
    @Resource
    private DetailDao detailDao;
    @Override
    public ResultVo<?> addAttention(Long userId, Long uid) {
        // 调用持久层 添加关注信息
        userDao.addAttentionByUid(userId, uid);
        //查询被关注人用户信息
        UserInfo userInfo = userDao.findUserInfoByUserId(userId);
        //组装数据
        Notice notice = Notice.builder().remark(AppConst.ATTENTION)
                .content(userInfo.getNickName() + AppConst.content_ATTENTION)
                .userId(uid).tagUserId(userId).build();
        Notice notice1 = detailDao.findNoticeByUserIdAndContent(notice);
        if (notice1 == null){
            detailDao.saveNotice(notice);
        }
        return ResultVo.ok().build();
    }

    @Override
    public ResultVo<?> deleteAttention(Long userId, Long uid) {
        // 调用持久层 根据uid删除关注信息
        userDao.deleteAttentionByUid(userId, uid);
        return ResultVo.ok().build();
    }

    @Override
    public ResultVo<Map<String, Object>> showAttention(Long userId, Long rId) {
        Map<String, Object> map = null;
        // 判断关注表中是否存在该用户
        Map<String, Object> ridUser = userDao.findAttentionByUserIdAndRid(userId, rId);
        if (ridUser !=null){
            // 调用持久层 根据两个id 查询关注状态
            map = userDao.findAttentionStatusById(userId, rId);
            return ResultVo.ok().body(map);
        }
        int map1 = userDao.addAttentionByUidAndRid(userId, rId);
        return ResultVo.ok().body(map1);
}


    @Override
    public ResultVo<?> register(User user) {

        User u = userDao.findUserByTel(user.getTel());
        // 判断手机号是否已被注册
        if (u != null){
            return ResultVo.fail("手机号已被注册").body("telMsg");
        }
        // 如果手机号未注册,判断邮箱是否已被注册
        u = userDao.findUserByEmail(user.getEmail());

        if (u != null){
            return ResultVo.fail("邮箱已被注册").body("emailMsg");
        }

        // 保存数据到数据库
        userDao.saveUser(user);

        return ResultVo.ok().body(user);
    }

    @Override
    public ResultVo<User> saveUserInfo(UserInfo userInfo) {
        try {
            // 保存用户信息
            userDao.saveUserInfo(userInfo);
            // 准备发送邮件 获取当前注册的用户的邮箱
            User user = userDao.findUserById(userInfo.getUserId());

            return ResultVo.ok().body(user);
        } catch (Exception e) {
           return ResultVo.fail("数据插入失败").build();
        }
    }

    @Override
    public ResultVo<User> activeAccount(long userId) {

        String action = "用户注册";
        // 修改账户的状态为激活
        userDao.updateStatus(userId,1);
        // 赠送积分
        Map<String,Object> map = userDao.findScoreConfigByAction(action);

        if (map != null){
            // 说明查询到了 赠送积分的动作, 获取赠送积分的数量
            int score = Integer.parseInt(String.valueOf(map.get("score")));

            UserScore userScore = UserScore.builder()
                    .userId(userId)
                    .score(score)
                    .remark(action)
                    .build();
            // 赠送积分
            userDao.saveUserScore(userScore);
        }
        return ResultVo.ok().build();
    }

    @Override
    public ResultVo<User> login(String tel, String password, String linkUrl) {

        // 根据 手机号，查询 用户是否存在
        User user = userDao.findUserByTel(tel);

        if (user == null) {
            return ResultVo.fail("手机号未注册").build();
        }
        // 没有被激活，发送邮件
        if (user.getEnable() == UserStatus.DISABLED) {
            // 发送邮件
            SendMailUtils.sendMailForActiveAccount(user.getTel(), user.getId(),  user.getEmail());
            // 发邮件，并返回 登录页面
            return  ResultVo.fail("邮件已发送、请激活账户").build();
        }

        // 如果没有被激活， 判断是否拉黑
        if (user.getEnable() == UserStatus.BLOCK) {
            // 如果被拉黑
            return ResultVo.fail("账户被拉黑，请联系管理员").build();
        }

        // 如果 没有被拉黑 ， 判断是否被注销
        if (user.getEnable() == UserStatus.INVALID) {
            return ResultVo.fail("账户已被注销" ).build();
        }
        // 如果 账户被激活 ， 则 比较密码是否一致
        if (user.getEnable() == UserStatus.ENABLE) {
            // 如果 账户被启用， 判断密码是否和数据库的一致
            if (!Objects.equals(SecureUtil.md5(password),  user.getPassword())) {
                return ResultVo.fail("密码错误").build() ;
            }
            // 查询用户信息，并放到 user中
            UserInfo info = userDao.findUserInfoByUserId(user.getId()) ;
            user.setInfo(info);
            return ResultVo.ok().body(user);
        }
        // 其它状态
        return ResultVo.fail("账户状态未知错误、请联系管理员").build();
    }


    @Override
    public ResultVo<String> updatePassWord(String oldPassWord, String newPassWord, String confirmPassWord) {
        HttpServletRequest request = ContextUtils.getRequest();
        User user = (User) request.getSession().getAttribute(AppConst.LOGIN_FLAG);
        if (user != null){
            if (!Objects.equals(user.getPassword(),SecureUtil.md5(oldPassWord))){
                return ResultVo.fail("原密码不正确").body("oldPassWord");
            }
            if (Objects.equals(oldPassWord,newPassWord)){
                return ResultVo.fail("新老密码不能相同").body("newPassWord");
            }
            if (!Objects.equals(newPassWord,confirmPassWord)){
                return ResultVo.fail("新密码与确认密码不一致").body("confirmPassWord");
            }
            userDao.updatePassWord(user.getId(),newPassWord);
            return ResultVo.ok().build();
        }
        return ResultVo.fail("当前无用户登录,不能进行密码修改").body("noUser");
    }

    @Override
    public ResultVo<List<Map<String, Object>>> staticsScore(Long userId) {
        // 调用持久层 查询 统计的信息
        List<Map<String,Object>> list = userDao.findUserStaticsScore(userId);

        return ResultVo.ok().body(list);
    }

    @Override
    public ResultVo<Page<Map<String, Object>>> detailScore(Long userId,Page<Map<String,Object>> pageBean) {

        // 查询指定页码的数据
        List<Map<String, Object>> list = userDao.findUserScoreByUserId(userId,pageBean);
        // 查询满足条件的总个数
        int count = userDao.findUserScoreCountByUserId(userId);

        pageBean.setList(list);
        pageBean.setTotalRows(count);
        return ResultVo.ok().body(pageBean);
    }

    @Override
    public ResultVo<String> updateNickNameByUserId(String nickName, Long id) {
        userDao.updateNickNameByUserId(nickName,id);
        return ResultVo.ok().body(nickName);
    }

    @Override
    public ResultVo<String> updateSexByUserId(String sex, Long id) {
        userDao.updateSexByUserId(sex,id);
        String sexDisplay = UserInfo.builder().sex(sex).build().getSexDisplay();
        return ResultVo.ok().body(sexDisplay);
    }

    @Override
    public ResultVo<String> updatePhoto(UserInfo info) {

        // 调用持久层将数据写入数据库
        userDao.updatePhoto(info);

        return ResultVo.ok().body("/user/photo?v=" + System.currentTimeMillis());
    }

    @Override
    public ResultVo<String> updateEmial(User user,String oldEmail, String newEmail) {
        if (!user.getEmail().equals(oldEmail)){
            return ResultVo.fail("原邮箱不正确").body("oldEmail");
        }
        String regex = "^\\w+@\\w+(\\.\\w+)+$";
        if (!Pattern.matches(regex,newEmail)){
            return ResultVo.fail("新邮箱格式不正确").body("newEmail");
        }
        if (newEmail.equals(oldEmail)){
            return ResultVo.fail("新老邮箱不能相同").body("oldEmail");
        }
        User user1 = userDao.findUserByEmail(newEmail);

        if (user1 != null){
            return ResultVo.fail("该新邮箱已被注册").body("newEmail");
        }

        userDao.updateEmail(user.getId(),newEmail);

        newEmail = "***" + newEmail.substring(newEmail.indexOf('@'));

        return ResultVo.ok().body(newEmail);
    }

    @Override
    public ResultVo<User> findPassWord(String tel, String email) {
        User userByTel = userDao.findUserByTel(tel);
        if (userByTel == null){
            return ResultVo.fail("手机号未注册").build();
        }
        if (!Objects.equals(userByTel.getEmail(),email)){
            return ResultVo.fail("邮箱必须是注册时绑定的邮箱").build();
        }

        sendMailForFindPassWord(tel,userByTel.getId(),email);
        return ResultVo.ok().message("密码找回邮件已发送").body(userByTel);
    }


    public static void sendMailForFindPassWord(String tel, Long userId, String email) {

        long minus = 10 ;
        LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(minus);

        String lastTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        String password = "123456";
        // 这个字符串中的任何数据不允许被篡改
        String message = "u=" + userId + "&n=" + password;

        String sign = RSAUtils.sign(message);

        HttpServletRequest request = ContextUtils.getRequest() ;

        String linkUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
                + request.getContextPath() + "/password/active?u=" + userId + "&n=" + password + "&sign=" + sign;

        // 设置邮件的内容
        String content = """
                <p>尊敬的%s用户,</p>
                <p>请您与%s之前在本网站找回密码,你的新密码是<b style="color:red">%s</b></p>
                <p>请点击下方的链接,激活新密码</p>     
                <p><a href="%s">%s</a></p>
                <p>如果不是您本人操作、请忽略该邮件，以确保您的账号安全</p>
                """;

        // 邮件正文内容
        content = content.formatted(tel,lastTime,password, linkUrl, linkUrl);
        // 发送邮件  设置邮件的主题
        MailUtil.send(email, "Haredot-账户激活", content, true);
    }

    @Override
    public void initePassword(Long id) {
        userDao.initePassword(id);
    }

    @Override
    public ResultVo<Page<Map<String, Object>>> detailAttention(Long userId, Page<Map<String, Object>> pageBean) {
        Map<String,Object> map = new HashMap<>();
        // 查询指定页码的数据
        List<Map<String,Object>> list = userDao.findUserAttention(userId,pageBean);
        // 查询满足条件的总个数
        int count = userDao.findUserAttentionCountByUserId(userId);

        pageBean.setList(list);
        pageBean.setTotalRows(count);
        return ResultVo.ok().body(pageBean);
    }

    @Override
    public ResultVo<List<Map<String, Object>>> fenNum(Long id) {
        // 调用持久层 查询统计的信息
        List<Map<String,Object>> list = userDao.findUserFenNumById(id);
        return ResultVo.ok().body(list);
    }

    @Override
    public ResultVo<List<Map<String, Object>>> fenNum2(Long userId) {
        // 调用持久层 查询统计的信息
        List<Map<String,Object>> list = userDao.findUserFenNumById2(userId);
        return ResultVo.ok().body(list);
    }

    @Override
    public int uploadStatusById(Long uid) {
        // 调用持久层 修改数据
        return userDao.uploadStatusByUid(uid);

    }

    /**
     * @description 查询用户收藏资源信息
     * @date 2022/9/26 22:56
     * @auther XuHuanDong
     */
    @Override
    public ResultVo<Page<Map<String, Object>>> findCollect(User user ,Page<Map<String,Object>> pageBean) {
        //根据用户id 查询用户收藏的资源 查询指定页码的数据
        List<Map<String, Object>> list = userDao.queryCollectResourceByUseId(user.getId(),pageBean);
       if (!list.isEmpty()){
           // 查询满足条件的总个数
           int count = userDao.queryCollectResourceCountByUseId(user.getId());
           pageBean.setList(list);
           pageBean.setTotalRows(count);
           return ResultVo.ok().body(pageBean);
       }
        return ResultVo.fail("你还未收藏资源").build();
    }

    @Override
    public ResultVo<Page<Map<String, Object>>> findCol(Long userId, Page<Map<String, Object>> pageBean) {
        //根据用户id 查询用户的资源 查询指定页码的数据
        List<Map<String, Object>> list = userDao.queryCollectResByUseId(userId,pageBean)
                .stream().filter(q->q.get("status").equals(1))
                .map(p->{
                    p.put("one",userDao.qureyIdByPid((Long) p.get("pid")));
                    return p;
                }).toList();
        if (!list.isEmpty()){
            // 查询满足条件的总个数
            int count = userDao.queryCollectResCountByUseId(userId);
            pageBean.setList(list);
            pageBean.setTotalRows(count);
            return ResultVo.ok().body(pageBean);
        }
        return ResultVo.fail("暂无").build();
    }
}
